﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TimePlayer
{
    public partial class Form1 : Form
    {
        // タイミングを保持
        List<long> timings = new List<long>();
        List<Tim> tims = new List<Tim>();

        // タイマの役割
        enum TimerRole
        {
            CountDown,
            Playing,
            NoRole,
            INVALID,
        }
        TimerRole tr = TimerRole.NoRole;
        int forOnlyCountDown=0;

        // ストップウォッチ
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnReadFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.FileName = "NewTiming.txt";
            ofd.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)+@"\";
            ofd.RestoreDirectory = true;
            ofd.ShowHelp = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    System.IO.StreamReader sr = new System.IO.StreamReader(
                        ofd.FileName, Encoding.GetEncoding("Shift_JIS"));
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        timings.Add(long.Parse(line));
                    }
                    foreach (long l in timings)
                    {
                        tbTimings.AppendText(l.ToString() + Environment.NewLine);
                        tims.Add(new Tim(l));
                    }
                    btnPlay.Enabled = true;

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to read" + ofd.FileName + "\t" + ex.Message);
                    btnPlay.Enabled = false;
                    tbTimings.Text = "";
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            btnPlay.Enabled = false;
            timer1.Enabled = false;
            pbStage.Refresh();
        }

        private void btnPlay_Click(object sender, EventArgs e)
        {
            timer1.Interval = 1000;
            timer1.Enabled = true;
            forOnlyCountDown = 3;
            tr = TimerRole.CountDown;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (tr)
            {
                case TimerRole.CountDown:
                    if (forOnlyCountDown > 0)
                    {
                        Console.Beep();
                        forOnlyCountDown -= 1;
                    }
                    else
                    {// Playへ移行
                        Console.Beep(3000, 200);
                        timer1.Interval = 10;
                        tr = TimerRole.Playing;
                        sw.Reset();
                        sw.Start();
                    }
                    break;
                case TimerRole.Playing:
                    lblTimer.Text = ((double)sw.ElapsedMilliseconds / 1000).ToString();
                    pbStage.Refresh();
                    break;
                default:
                    break;
            }
        }

        private void pbStage_Paint(object sender, PaintEventArgs e)
        {
            Pen pen = new Pen(Brushes.Black);
            Brush brush = new SolidBrush(Color.Red);

            e.Graphics.DrawLine(pen, 50, 50, 450, 50);
            e.Graphics.DrawLine(pen, 80, 20, 80, 80);

            if (tr == TimerRole.Playing)
            {
                long now = sw.ElapsedMilliseconds;
                long dt = timer1.Interval / 2;
                long echoLen = 50;
                foreach (long tim in timings)
                {
                    if (((now - dt) < tim) && (tim < (now + echoLen + dt)))
                    {
                        e.Graphics.FillEllipse(brush, 55, 25, 50, 50);
                    }
                }
                foreach (Tim tim in tims)
                {
                    tim.paint(e.Graphics, now);
                }
            }

            pen.Dispose();
        }
    }

    class Tim
    {
        long tim;
        long speed = 400;    // [pixel/sec]
        int x0 = 50;
        int y0 = 50;
        int rad = 10;

        public void paint(Graphics g, long t)
        {
            int posx = x0 + (int)(speed * (tim - t) / 1000);
            g.FillEllipse(Brushes.Red, posx - rad, y0 - rad, 2 * rad, 2 * rad);
        }

        public Tim(long tim)
        {
            this.tim = tim;
        }
    }
}
